EC2 → S3: VPC Endpoint vs NAT (Motion Path Simulator)

Private-subnet EC2 uploading to S3: compare a VPC Gateway Endpoint (private path) with a NAT Gateway + Internet Gateway (public path). See routes, IAM, and flow logs in one interactive page with curved packet paths.

Big Picture: Two Paths, One S3 Bucket

Your EC2 instance sits in a private subnet and needs to upload reports to an S3 bucket. It can reach S3 in two main ways:

VPC Endpoint – Private Path

Recommended
  • No public IP, no Internet hop.
  • Traffic stays on the AWS backbone via a Gateway VPC Endpoint.
  • Cheaper data transfer for S3 + stronger security posture.

NAT Gateway – Public Path

Fallback / Legacy
  • EC2 sends traffic to a NAT Gateway in a public subnet.
  • NAT uses an Elastic IP via the Internet Gateway to reach S3.
  • More cost + Internet exposure; acceptable but not ideal for internal workloads.

Security Model

IAM + VPCE + Bucket Policy
  • IAM role on EC2 → who you are.
  • Bucket policy → who may enter the bucket.
  • VPC endpoint policy → who may use the private door.
  • Combine all three to lock S3 down to the workload and the VPC.

Route Tables – Why VPC Endpoint Wins

The longest prefix match rule decides whether S3 traffic goes to the VPC Endpoint or NAT Gateway.

Private Subnet Route Table

For EC2 (10.0.1.0/24)
RT – Private 10.0.0.0/16 → local pl-xxxxS3 → vpce-1234567890abcdef (S3 prefix list → VPC Endpoint) 0.0.0.0/0 → nat-0abc123def456 (NAT Gateway)
  • S3 traffic matches the prefix list route (more specific) → VPC Endpoint.
  • Only “everything else” uses 0.0.0.0/0 → NAT.

Public Subnet Route Table

For NAT Subnet
RT – Public 10.0.0.0/16 → local 0.0.0.0/0 → igw-0123abcd4567
  • NAT sends outgoing traffic to the Internet Gateway.
  • From there, traffic reaches S3 public endpoints.

Decision Summary

  • Have S3 prefix list → VPC Endpoint? → Private path wins.
  • No S3-specific route? → EC2 uses NAT + IGW.
  • Mixed mode is common in brownfield environments.

Architecture – VPC, Subnets, NAT, VPCE, S3

High-level layout for a single-AZ teaching scenario (you can extend to multi-AZ easily).

VPC Layout

  • VPC: 10.0.0.0/16
  • Public Subnet: 10.0.0.0/24 (NAT Gateway)
  • Private Subnet: 10.0.1.0/24 (EC2 instance)
  • Internet Gateway attached to VPC.

Key Components

  • EC2 (private subnet, no public IP).
  • NAT Gateway (public subnet, Elastic IP).
  • VPC Gateway Endpoint for S3.
  • S3 bucket my-logs-bucket in the same Region.

Business Story

  • Finance EC2 instance generates nightly sales reports.
  • Uploads them to S3 for long-term storage and analytics.
  • Security team wants: no public S3, no direct Internet from EC2.
  • Solution: force traffic via VPC Endpoint + restricted bucket policy.

Simulation – Curved Path from EC2 to S3

Watch the packet travel along curved paths. Blue = VPC Endpoint (private), Yellow = NAT + IGW (public). The log panel shows a CloudWatch-style trace of each hop.

Region: ap-southeast-1
VPC 10.0.0.0/16
EC2 Instance
Private Subnet
VPC Gateway Endpoint
com.amazonaws.ap-southeast-1.s3
NAT Gateway
Public Subnet + EIP
Internet Gateway
Amazon S3 Bucket
my-logs-bucket
VPC Endpoint (Private Path)
NAT + IGW (Public Path)

Run the Simulation

Click a button below to send a “report upload” from EC2 to S3.

Routing Logic (Teaching Notes)
  • S3 traffic matches the S3 prefix list route → VPC Endpoint (blue path).
  • If that route is missing/misconfigured, 0.0.0.0/0 → NAT (yellow path).
  • CloudWatch logs help you detect “unexpected” NAT usage to S3.
Business Use Case – Nightly Sales Reports
A finance EC2 instance in a private subnet uploads nightly sales reports to S3. • Normal operation: blue path via VPC Endpoint (no Internet). • Misconfig or emergency: yellow path via NAT + IGW. You can alert whenever the finance EC2 uses the NAT path to reach S3.
CloudWatch-style Flow Logs Source: EC2 10.0.1.10 → S3 my-logs-bucket
Tip: Ask students which path is cheaper and which has a smaller attack surface.

IAM Role & Bucket Policy

Networking decides how you reach S3. IAM and bucket policies decide whether you may do so.

EC2 Instance Profile Role

Trust Policy
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "ec2.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}
Permissions Policy
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["s3:PutObject","s3:GetObject"],
    "Resource": "arn:aws:s3:::my-logs-bucket/*"
  }]
}

Bucket Policy – Lock to VPC Endpoint

Bucket Policy
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": ["s3:GetObject","s3:PutObject"],
    "Resource": "arn:aws:s3:::my-logs-bucket/*",
    "Condition": {
      "StringEquals": {
        "aws:SourceVpce": "vpce-1234567890abcdef"
      }
    }
  }]
}

Flow Summary

1. EC2 uses its instance profile role to sign S3 requests.
2. Network sends packets via VPCE or NAT.
3. S3 checks: bucket policy + IAM + optional VPCE policy.
4. If VPCE condition fails, access is denied & logged.

Quick Quiz

Use this as a formative check during class.

1. Why is a VPC Endpoint usually preferred over NAT for S3 access?
Cheaper and keeps traffic on AWS private network
Because NAT cannot reach S3
Because it gives the EC2 a public IP
2. What decides whether S3 traffic uses VPC Endpoint or NAT?
The EC2 instance type
The longest prefix match in the route table
The S3 bucket name
3. Which statement best describes the role of the bucket policy?
It assigns public IPs to EC2
It decides which principals and network sources can access the bucket
It configures NAT routing

CLI & Boto3 – Upload Example

Same IAM role, different network path – the application code doesn’t change.

AWS CLI from EC2

aws s3 cp report-2025-11-30.json s3://my-logs-bucket/reports/ \ 
  --region ap-southeast-1
  • Instance profile role provides credentials automatically.
  • Network path (VPCE or NAT) is determined by route tables.

Python Boto3 Snippet

import boto3
s3 = boto3.client("s3")

s3.upload_file(
    Filename="report-2025-11-30.json",
    Bucket="my-logs-bucket",
    Key="reports/report-2025-11-30.json"
)
  • No endpoint hard-coded → easier to switch from NAT to VPCE.
  • Good pattern for refactoring legacy workloads.

Failure Mode – When Policies Don’t Agree

Use this as a mini runbook: “EC2 cannot upload to S3, but ping works.”

Common Problems

  • VPC Endpoint exists, but route table not updated.
  • Bucket policy missing aws:SourceVpce or using wrong VPCE ID.
  • IAM role lacks s3:PutObject permission.

Classroom Exercise

  • Break: remove S3 prefix route → traffic goes via NAT.
  • Observe: animation switches to yellow path; logs show NAT usage.
  • Fix: restore S3 prefix route + bucket policy; verify blue path again.